<?php
declare(strict_types=1);

namespace App\Service\Admin;

use App\Cache\CacheKey;
use App\Enum\Code;
use App\Exception\BusinessException;
use App\Model\Article;
use App\Repository\Admin\ArticleRepository;
use Hyperf\Di\Annotation\Inject;
use Hyperf\Redis\Redis;
use Hyperf\Utils\Collection;

class ArticleService
{
    #[Inject]
    private ArticleRepository $articleRepository;

    #[Inject]
    private Redis $redis;

    public function getReviewArticles(int $page, int $perPage)
    {
        $articles = $this->articleRepository->getReviewArticles($page, $perPage);

        return map_paginator($articles, function (Article $article) {
            $sensitiveInfo = $this->redis->hGetAll(CacheKey::articleSensitiveWords($article->id));

            $article->append([
                'sensitiveInfo' => $sensitiveInfo,
            ]);
        });
    }

    public function getArticleDetail(int $id)
    {
        return $this->articleRepository->getArticleDetail($id);
    }

    public function review(array $data, int $authUserId)
    {
        $ids = $data['ids'];
        $approved = $data['approved'];

        $count = $this->articleRepository->getReviewArticleCountBy($ids);

        if ($count !== count($ids)) {
            throw new BusinessException(Code::RequestParamError, '审核的文章有不处于待审核状态的', ['ids' => $ids]);
        }

        $haveSensitiveWordArticles = $this->redis->sMembers(CacheKey::haveSensitiveWordArticles());
        [$sensitiveIds, $normalIds] = Collection::make($ids)->partition(function ($id) use ($haveSensitiveWordArticles) {
            return in_array($id, $haveSensitiveWordArticles);
        });

        $this->articleRepository->approve($normalIds, $approved);
        if ($approved) {
            $sensitiveIds->each(function ($id) use ($authUserId) {
                $this->redis->hSet(CacheKey::reviewControversialResult($id), $authUserId, true);
            });
        }
    }

    // 审核带有内容争议的文章
    // 审核为有大于1个admin角色通过，则通过
    // 有争议的内容即内容中带有敏感词的
    public function reviewControversial(int $id, int $authUserId, bool $approved)
    {
        if (!$approved) {
            return ;
        }

        $approvedCount = $this->redis->hLen(CacheKey::reviewControversialResult($id));
        if ($approvedCount >= 1) {
            $this->articleRepository->approve([$id], true);
            $this->redis->del(CacheKey::reviewControversialResult($id));
        } else {
            $this->redis->hSet(CacheKey::reviewControversialResult($id), $authUserId, true);
        }
    }
}